#include "./BSP/SPI/myspi.h"
#include "spi.h"

SPI_HandleTypeDef g_spi1_handler; /* SPI1句柄 */
#define g_spi1_handler hspi1

/**
 * @brief       SPI1初始化
 * @param       无
 * @retval      无
 * @note        主机模式，8位数据，禁止硬件片选
 *              时钟空闲状态为高电平，第二个边沿采样
 */
void spi1_init(void)
{
    SPI1_SPI_CLK_ENABLE(); /* SPI1时钟使能 */

    g_spi1_handler.Instance = SPI1_SPI;                                /* SPI1 */
    g_spi1_handler.Init.Mode = SPI_MODE_MASTER;                        /* 设置为主模式 */
    g_spi1_handler.Init.Direction = SPI_DIRECTION_2LINES;              /* 双线模式 */
    g_spi1_handler.Init.DataSize = SPI_DATASIZE_8BIT;                  /* 8位数据帧 */
    g_spi1_handler.Init.CLKPolarity = SPI_POLARITY_HIGH;               /* 时钟空闲状态为高电平 */
    g_spi1_handler.Init.CLKPhase = SPI_PHASE_2EDGE;                    /* 第二个边沿采样 */
    g_spi1_handler.Init.NSS = SPI_NSS_SOFT;                            /* 软件片选控制 */
    g_spi1_handler.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; /* 波特率预分频值为256 */
    g_spi1_handler.Init.FirstBit = SPI_FIRSTBIT_MSB;                   /* 数据从MSB位开始传输 */
    g_spi1_handler.Init.TIMode = SPI_TIMODE_DISABLE;                   /* 关闭TI模式 */
    g_spi1_handler.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;   /* 关闭CRC校验 */
    g_spi1_handler.Init.CRCPolynomial = 7;                             /* CRC多项式(不使用) */
    HAL_SPI_Init(&g_spi1_handler);                                     /* 初始化SPI */

    __HAL_SPI_ENABLE(&g_spi1_handler); /* 使能SPI1 */

    spi1_read_write_byte(0XFF); /* 启动传输, 实际上就是产生8个时钟脉冲, 达到清空DR的作用, 非必需 */
}

/**
 * @brief       SPI底层驱动，时钟使能，引脚配置
 * @param       hspi: SPI句柄
 * @retval      无
 * @note        此函数会被HAL_SPI_Init()调用
 *              初始化SCK、MISO、MOSI引脚为复用推挽输出
 */
//void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
//{
//    GPIO_InitTypeDef gpio_init_struct;
//    
//    if (hspi->Instance == SPI1_SPI)
//    {
//        SPI1_SCK_GPIO_CLK_ENABLE();  /* SCK脚时钟使能 */
//        SPI1_MISO_GPIO_CLK_ENABLE(); /* MISO脚时钟使能 */
//        SPI1_MOSI_GPIO_CLK_ENABLE(); /* MOSI脚时钟使能 */

//        /* SCK引脚配置 */
//        gpio_init_struct.Pin = SPI1_SCK_GPIO_PIN;
//        gpio_init_struct.Mode = GPIO_MODE_AF_PP;        /* 复用推挽输出 */
//        gpio_init_struct.Pull = GPIO_PULLUP;            /* 上拉 */
//        gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;  /* 高速 */
//        HAL_GPIO_Init(SPI1_SCK_GPIO_PORT, &gpio_init_struct);

//        /* MISO引脚配置 */
//        gpio_init_struct.Pin = SPI1_MISO_GPIO_PIN;
//        HAL_GPIO_Init(SPI1_MISO_GPIO_PORT, &gpio_init_struct);

//        /* MOSI引脚配置 */
//        gpio_init_struct.Pin = SPI1_MOSI_GPIO_PIN;
//        HAL_GPIO_Init(SPI1_MOSI_GPIO_PORT, &gpio_init_struct);
//    }
//}

/**
 * @brief       SPI1速度设置
 * @param       speed: SPI1时钟分频系数，取值为SPI_SPEED_2~SPI_SPEED_256
 * @retval      无
 * @note        SPI1时钟来自APB2(PCLK2)，为72MHz
 *              SPI速度 = PCLK2 / 2^(speed + 1)
 *              speed = 0，对应SPI_BAUDRATEPRESCALER_2，速度为36MHz
 *              speed = 7，对应SPI_BAUDRATEPRESCALER_256，速度为281.25KHz
 */
void spi1_set_speed(uint8_t speed)
{
    assert_param(IS_SPI_BAUDRATE_PRESCALER(speed << 3)); /* 判断有效性 */
    __HAL_SPI_DISABLE(&g_spi1_handler);                  /* 关闭SPI */
    g_spi1_handler.Instance->CR1 &= 0XFFC7;              /* 清除CR1寄存器第3-5位(BR[2:0])波特率控制位 */
    g_spi1_handler.Instance->CR1 |= speed << 3;          /* 设置SPI速度 */
    __HAL_SPI_ENABLE(&g_spi1_handler);                   /* 使能SPI */
}

/**
 * @brief       SPI1读写一个字节
 * @param       txdata: 要发送的字节
 * @retval      接收到的字节
 * @note        SPI1采用全双工通信，发送的同时也在接收
 */
uint8_t spi1_read_write_byte(uint8_t txdata)
{
    uint8_t rxdata;
    HAL_SPI_TransmitReceive(&g_spi1_handler, &txdata, &rxdata, 1, 1000);
    return rxdata; /* 返回接收到的数据 */
}
